package com.xq.controller;

import com.xq.apis.AuthApis;
import com.xq.constants.ErrorCodeConstants;
import com.xq.entity.UmsUsers;
import com.xq.service.AuthService;
import com.xq.service.IUmsUsersService;
import com.xq.service.SmsService;
import com.xq.utils.JwtBlacklistManager;
import com.xq.utils.JwtTokenProvider;
import com.xq.vo.JsonVO;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiOperation;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.http.ResponseEntity;
import org.springframework.security.core.Authentication;
import org.springframework.security.core.context.SecurityContext;
import org.springframework.security.core.context.SecurityContextHolder;
import org.springframework.security.crypto.password.PasswordEncoder;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.RestController;

import javax.servlet.http.HttpServletRequest;
import java.util.HashMap;

@Api(tags = "用户登录")
@RestController
@RequestMapping("/api/auth")
public class AuthController implements AuthApis {

    //TODO 注册的时候要插入用户的角色信息

    @Autowired
    private AuthService authService;

    @Autowired
    private SmsService smsService;

    @Autowired
    private IUmsUsersService iUmsUsersService;

    @Autowired
    private PasswordEncoder passwordEncoder;

    @Autowired
    private JwtBlacklistManager jwtBlacklistManager;

    @Autowired
    private JwtTokenProvider jwtTokenProvider;

    @ApiOperation("发送验证码")
    @PostMapping("/sendCode")
    @Override
    public JsonVO<String> send(@RequestParam String phone) {
        smsService.sendVerificationCode(phone);
        return JsonVO.success("已发送验证码");
    }

    @ApiOperation("手机验证码注册账户")
    @PostMapping("/register")
    @Override
    public ResponseEntity<JsonVO<Object>> register(@RequestParam String username,@RequestParam String password) {
        //TODO 这里要捕捉异常的话 service方法中就要抛出异常
        try {
            authService.register(username, password);
            return ResponseEntity.ok(new JsonVO<>(200,"注册成功",null));
        }catch (RuntimeException e){
            HashMap<String,String> map = new HashMap<>();
            map.put("username",username);
            return ResponseEntity.badRequest().body(new JsonVO<>(400,e.getMessage(), map));
        }

    }

    @ApiOperation("手机验证码登录")
    @PostMapping("/User/loginByCode")
    @Override
    public ResponseEntity<JsonVO<Object>> loginByCode(@RequestParam String phone,@RequestParam String code) {
        try {
            authService.loginByCode(phone, code);
            //TODO 改为使用工具类中的方法
            // 生成JWT Token
            String token = jwtTokenProvider.generateToken(phone);
            HashMap<String,String> map = new HashMap<>();
            map.put("token",token);
            return ResponseEntity.ok(new JsonVO<>(200,"登录成功",map));
        }catch (RuntimeException e){
            return ResponseEntity.badRequest().body(new JsonVO<>(400,e.getMessage(),null));
        }
    }

    @ApiOperation("用户密码登录")
    @PostMapping("/User/loginByUsername")
    @Override
    public ResponseEntity<JsonVO<Object>> loginByUsername(@RequestParam String username,@RequestParam String password) {

        try{
            authService.loginByUsername(username, password);
            // 生成JWT Token
            String token = jwtTokenProvider.generateToken(username);
            HashMap<String,String> map = new HashMap<>();
            map.put("token",token);
            return ResponseEntity.ok(new JsonVO<>(200,"登录成功",map));
        }catch (RuntimeException e){
            return ResponseEntity.badRequest().body(new JsonVO<>(400,e.getMessage(),null));
        }
    }

    @ApiOperation("设置账户名或者密码")
    @PostMapping("/User/setUsernameAndPassword")
    @Override
    public JsonVO<String> setUsernameAndPassword(@RequestParam String username,@RequestParam String password ,@RequestParam String phone) {
       try{
           authService.setUserByUsername(username, password, phone);
           return JsonVO.success("设置成功");
       }catch (RuntimeException e){
           return JsonVO.fail("设置失败"+e.getMessage());
       }
    }

    /**
     * 手机验证码找回 可能是在未登录的情况下 用户忘记了密码找回 也可能是用户在登录的情况下 忘记了密码开始找回
     * @param phone
     * @param code
     * @param newPassword
     * @return
     */
    @ApiOperation("手机号验证码找回密码")
    @PostMapping("/User/findPasswordByPhone")
    @Override
    public JsonVO<String> findPasswordByPhone(@RequestParam String phone,@RequestParam String code,@RequestParam String newPassword) {
        //判断验证码是否正确
        if (!smsService.validateCode(phone,code)){
            return JsonVO.success(ErrorCodeConstants.INVALID_VERIFICATION_CODE);
        }
        //判断用户是否存在
        UmsUsers user=iUmsUsersService.getUserByPhone(phone);
        if (user==null){
            return JsonVO.fail(ErrorCodeConstants.USER_NOT_FOUND);
        }


        //这里要对两种可能做处理
        //获取当前用户的token
        //String token = SecurityContextHolder.getContext().getAuthentication().getCredentials().toString();
        //获取当前用户的token
        String token = null;
        SecurityContext context = SecurityContextHolder.getContext();
        if (context != null) {
            Authentication authentication = context.getAuthentication();
            if (authentication != null) {
                Object credentials = authentication.getCredentials();
                if (credentials instanceof String) {
                    token = (String) credentials;
                    if (token.isEmpty()){
                        token=null;
                    }
                }
            }
        }

        //token存在意味这是在登录状态下
        if (token!=null){
            //重新设置密码后使springSecurity中的jwt失效
            jwtBlacklistManager.addToBlacklist(token);
        }

        //更新密码
        user.setPasswordHash(passwordEncoder.encode(newPassword));
        //更新数据
        int i = iUmsUsersService.setUserAndPassword(user);
        if (i<0){
            return JsonVO.fail(ErrorCodeConstants.ERROR);
        }

        return JsonVO.success(ErrorCodeConstants.SUCCESS);
    }

    @PostMapping("/User/regainSetPassword")
    @ApiOperation("重新设置密码")
    @Override
    public JsonVO<String> reagainSetPassword(@RequestParam String oldPassword,@RequestParam String newPassword,HttpServletRequest request) {
        //1.获取当前的登录用户
        Authentication authentication=SecurityContextHolder.getContext().getAuthentication();
        // 这里可能会有个问题，就是我不知道使用用户名登录的还是用手机号登录的，如果传进来的用户名是个手机号，那就不行了 那就验证两遍？账号一遍 或者 用户名一遍
        //问题解决了，我把用户字段长度修改为了10 它不可能是手机号了
        String username=authentication.getName();
        //TODO 未完成
        //这里要得到一个user 然后修改它里面的密码
        UmsUsers user = iUmsUsersService.findUserUnknown(username);
        if (user==null){
            return JsonVO.fail(ErrorCodeConstants.USER_NOT_FOUND);
        }

        //校验旧的密码是否正确
        if (!passwordEncoder.matches(oldPassword,user.getPasswordHash())){
            return JsonVO.fail(ErrorCodeConstants.PASSWORD_MISMATCH);
        }

        //校验成功的话开始更新密码
        user.setPasswordHash(passwordEncoder.encode(newPassword));

        // 从请求头中获取当前用户的token
        String token = request.getHeader("Authorization");
        if (token != null && token.startsWith("Bearer ")) {
            token = token.substring(7); // 去掉 "Bearer " 前缀
        }

        iUmsUsersService.setUserAndPassword(user);

        //token存在意味这是在登录状态下
        if (token!=null){
            //重新设置密码后使springSecurity中的jwt失效
            jwtBlacklistManager.addToBlacklist(token);
        }

        return JsonVO.success(ErrorCodeConstants.SUCCESS);
    }

    @PostMapping("/User/reaginSetUsername")
    @ApiOperation("重新设置用户名")
    @Override
    public JsonVO<String> reagainSetUsername(@RequestParam String newUsername, HttpServletRequest request) {

        //获取当前的登录用户名
        Authentication authentication=SecurityContextHolder.getContext().getAuthentication();
        String username=authentication.getName();
        UmsUsers user = iUmsUsersService.findUserUnknown(username);
        if (user==null){
            return JsonVO.fail(ErrorCodeConstants.USER_NOT_FOUND);
        }

        //判断用户名是否存在
        UmsUsers user1 = iUmsUsersService.getUserByUsername(newUsername);
        if (user1!=null){
            return JsonVO.fail(ErrorCodeConstants.USER_ALREADY_EXISTS);
        }

        user.setUsername(newUsername);


        //这里要对两种可能做处理
        //获取当前用户的token
        //String token = SecurityContextHolder.getContext().getAuthentication().getCredentials().toString();
        //获取当前用户的token
        /*String token = null;
        SecurityContext context = SecurityContextHolder.getContext();
        if (context != null) {
            Authentication authentication1 = context.getAuthentication();
            if (authentication1 != null) {
                Object credentials = authentication1.getCredentials();
                if (credentials instanceof String) {
                    token = (String) credentials;
                    if (token.isEmpty()){
                        token=null;
                    }
                }
            }
        }*/

        // 从请求头中获取当前用户的token
        String token = request.getHeader("Authorization");
        if (token != null && token.startsWith("Bearer ")) {
            token = token.substring(7); // 去掉 "Bearer " 前缀
        }

        iUmsUsersService.setUserAndPassword(user);

        //token存在意味这是在登录状态下
        if (token!=null){
            //重新设置密码后使springSecurity中的jwt失效
            jwtBlacklistManager.addToBlacklist(token);
        }

        return JsonVO.success(ErrorCodeConstants.SUCCESS);
    }

    @PostMapping("/User/logOut")
    @ApiOperation("登出账号")
    @Override
    public JsonVO<String> logOut(HttpServletRequest request) {

        // 从请求头中获取当前用户的token
        String token = request.getHeader("Authorization");
        if (token != null && token.startsWith("Bearer ")) {
            token = token.substring(7); // 去掉 "Bearer " 前缀
        }

        //token存在意味这是在登录状态下
        if (token!=null){
            //重新设置密码后使springSecurity中的jwt失效
            jwtBlacklistManager.addToBlacklist(token);
        }
        SecurityContextHolder.clearContext();

        return JsonVO.success(ErrorCodeConstants.SUCCESS);
    }
}
